/**
 * 名字标签 2019
 */

function createScene(context) {
	let t = new NameTagScene(context);
	let scene = new context.Scene({
		require : [],
		init : (libs) => t.init(libs),
		destroy : () => t.destroy(),
		collectInfo : () => t.collectInfo(),
		onMessage : (key, data) => t.onMessage(key, data),
	});
	t.sendStatus = scene.sendStatus;
	return scene;
};

/*
 * HTML 设置方案
 * #main
 *   #content (底层, 100%x100%, 含 ZRender), 放计时器挂件
 */

/**
 * 要返回的场景的主体
 */
class NameTagScene {

	/**
	 * 当前的挂件
	 */
	pendant = null;
	/**
	 * 参数：当前正在播放的 index
	 */
	current = -1;
	/**
	 * 参数：所有 tag 的数据，是个Map，
	 * 每个键为：
	 *   屏幕自己为 tag 设置的 id 号 (int), 在该屏幕内唯一
	 * 每个元素含：
	 * {
	 *   "id" : <number>
	 *   "data" : {} // 每个模块自定义
	 *   "series" : <string> // 使用哪个挂件来工作 系列名
	 *   "pendant" : <string> // 使用哪个挂件来工作 挂件名
	 * }
	 */
	tags = {
		/*{
			"id" : ?,
			"data" : {
				"title" : "你要的标题",
				"content" : "123456789 123456789 123456789 123456789 123456789",
				"duration" : 12000
			},
			"series" : "name_tag",
			"pendant" : "title_and_content"
		}*/
	};
	
	// tag 的 ID 的列表
	order = [];

	// 下一个生成的 tag 的 ID. 递增的
	nextId = 1;
	/**
	 * 状态:
	 * 0 - 空的. 可能上一个挂件播放完了，或者根本就没有上一个挂件，是初始状态
	 * 1 - 正在加载挂件
	 * 2 - 正在播放
	 */
	status = 0;
	intervalHandler = null;
	context = null;

	constructor (context) {
		this.context = context;
		this.tick = this.tick.bind(this);
	};

	init() {
		/** @type {string | null} 存档位置 */
		this.saveSlot = this.context.parseInitParam().save;
		if (this.saveSlot != null) {
			this.save = new this.context.Save(`tag_2019::${this.saveSlot}`);
		}

		this.intervalHandler = requestAnimationFrame(this.tick);

		// 读取默认预设
		if (this.save) {
			this.fetchSave();
		} else {
			this.fetchPreset();
		}
	};

	fetchSave() {
		this.save.readJson()
			.then(d => this.readPlugins(d))
			.catch(e => {
				console.error(e);
				this.sendStatus();
			});
	}

	fetchPreset() {
		fetch(this.context.assetPath('preset/preset.json'))
			.then(d => d.json())
			.then(d => this.readPlugins(d))
			.catch(e => {
				console.error(e);
				this.sendStatus();
			});
	}

	readPlugins(data) {
		let def = data.plugins; // array
		if (!def) {
			throw { msg : '存档读取失败', data };
		}
		this.order.splice(0, this.order.length);
		this.current = -1;
		this.tags = {};
		for (let i = 0; i < def.length; i++) {
			let tagChunk = def[i];
			tagChunk.id = this.nextId ++;
			this.tags[tagChunk.id] = tagChunk;
			this.order.push(tagChunk.id);
		}
		this.sendStatus();
	}

	onMessage (name, arg) {
		switch (name) {
			case 'pushTag': {
				var tagChunk = JSON.parse(JSON.stringify(arg));
				if (tagChunk instanceof Array) {
					for (var i = 0; i < tagChunk.length; i++) {
						var tagChunk0 = tagChunk[i];
						tagChunk0.id = this.nextId ++;
						this.tags[tagChunk0.id] = tagChunk0;
						this.order.push(tagChunk0.id);
					}
				} else {
					tagChunk.id = this.nextId ++;
					this.tags[tagChunk.id] = tagChunk;
					this.order.push(tagChunk.id);
				}

				this.sendStatus();
			} break;

			case 'sortTags': {
				// 检查 arg. arg 是 { order : [...] }
				var order = arg.order;
				// 确保 order 是 number[], 无 null
				for (var i = order.length - 1; i >= 0; i --) {
					if (this.tags[order[i]] == null) {
						order.splice(i, 1);
					}
				}

				// 设值
				this.order = order;

				// 删除 tags 中多余的
				for (var key in this.tags) {
					var pass = false;
					for (var i = 0; i < order.length; i++) {
						if (order[i] == key) {
							pass = true;
							break;
						}
					}
					if (pass) {
						continue;
					}
					delete this.tags[key];
				}

				this.sendStatus();
			} break;

			case 'editTag': {
				var tagChunk = JSON.parse(JSON.stringify(arg));
				if (this.tags[tagChunk.id]) {
					this.tags[tagChunk.id] = tagChunk;
				}

				this.sendStatus();
			} break;

			case 'setSaveSlot': {
				this.saveSlot = arg.slot;
				if (this.saveSlot != null) {
					this.save = new this.context.Save(`tag_2019::${this.saveSlot}`);
				}
				if (arg.reload) {
					this.fetchSave();
				} else {
					this.sendStatus();
				}
			} break;
		}
	};

	/**
	 * 判断现在是否需要切换.
	 * 当上一个挂件播放完成后:
	 * 1. 调用上一个挂件的 destroy 方法
	 * 2. 删除挂件
	 * 3. 删除 DOM
	 * 4. 选择下一个挂件。如果没有，跳出
	 * 5. 创建 DOM
	 * 6. 创建挂件
	 */
	tick() {
		this.intervalHandler = requestAnimationFrame(this.tick)
		if (this.status != 0) {
			return;
		}

		if (this.pendant) {
			this.closeCurrentPendant();
			removeContextDOM("main");
		}

		if (this.order.length == 0) {
			return;
		}

		createContextDOM("main");
		this.turnToPendant((this.current + 1) % this.order.length);
	};

	closeCurrentPendant() {
		this.pendant.destroy();
		this.pendant = null;
	};

	turnToPendant(index) {
		this.current = index;
		this.status = 1;

		var initObj = {};
		var tagChunk = this.tags[this.order[index]];
		Object.assign(initObj, tagChunk.data);
		initObj.dom = 'content';

		this.context.createPendant(`${tagChunk.series}/${tagChunk.pendant}`, initObj).then(
			(pendant) => {
				this.pendant = pendant;
				this.status = 2;
				// 注入方法
				pendant.finished = () => {
					this.pendantFinished();
				}
				this.sendStatus();
			},
			(e) => {
				console.error(e);
				this.pendantFinished();
			}
		)
	};

	pendantFinished() {
		this.status = 0;
	};

	/**
	 * 收集状态数据
	 */
	collectInfo() {
		return {
			version : "0.4.1",
			tags : this.tags,
			order : this.order,
			current : this.current,
			slot : this.saveSlot,
		};
	};
}

/* **********
 * DOM 操作 *
 ********** */
function createContextDOM(mainDivId) {
	// HTML
	let maindiv = document.getElementById(mainDivId);

	let childdiv = document.createElement('div');
	childdiv.id = 'content';
	childdiv.style.position = 'absolute';
	childdiv.style.width = '100%';
	childdiv.style.height = '100%';
	maindiv.appendChild(childdiv);
}

function removeContextDOM(mainDivId) {
	let maindiv = document.getElementById(mainDivId);

	while (maindiv.hasChildNodes()) {
		maindiv.removeChild(maindiv.firstChild);
	}
}

export default createScene;
